package top.software.config;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @author: Amosen
 * @time: 2021-5-1
  *  注解
 */

// WebSocket核心功能类
@ServerEndpoint("/chat/{userId}")
@Component
public class WebSocketServer {

	// 记录当前在线连接数
	private static volatile int onlineCount = 0;

	// 存放每个客户端对应的WebSocket对象
	private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

	// 与某个客户端的连接对话，需要通过它来给客户端发送数据
	private Session session;

	// 接收userId
	private String userId = "";

	// 连接建立成功调用的方法
	@OnOpen
	public void onOpen(Session session, @PathParam("userId") String userId) {
		this.session = session;
		this.userId = userId;
		if (webSocketMap.containsKey(userId)) {
			webSocketMap.remove(userId);
			webSocketMap.put(userId, this);
		} else {
			webSocketMap.put(userId, this);
			addOnlineCount();
		}

		System.out.println(userId + "登录，" + "当前在线人数：" + getOnlineCount());
		try {
			ObjectMapper om = new ObjectMapper();
			List<String> users = new ArrayList<>();
			for (Entry<String, WebSocketServer> entry : webSocketMap.entrySet()) {
				users.add(entry.getKey());
			}
			String usersStr = om.writeValueAsString(users);
			sendMessage(usersStr);
		} catch (IOException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	// 连接关闭调用的方法
	@OnClose
	public void onClose() {
		if (webSocketMap.containsKey(userId)) {
			webSocketMap.remove(userId);
			subOnlineCount();
		}
		System.out.println(userId + "退出，当前在线人数：" + getOnlineCount());
	}

	// 接收到客户端消息后调用的方法
	@OnMessage
	public void onMessage(String message, Session session) throws IOException {
		System.out.println(userId + ":  " + message);
		if (!StringUtils.isEmpty(message)) {
			// 解析发送的报文
			ObjectMapper om = new ObjectMapper();
			try {
				Map<String, Object> value = om.readValue(message, Map.class);
				value.put("fromUserId", this.userId);
				String toUserId = (String) value.get("toUserId");
				if (!StringUtils.isEmpty(toUserId) && webSocketMap.containsKey(toUserId)) {
					webSocketMap.get(toUserId).sendMessage(om.writeValueAsString(value));
				} else {
					for (WebSocketServer wss : webSocketMap.values()) {
						wss.sendMessage(om.writeValueAsString(value));
					}
				}

			} catch (JsonProcessingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@OnError
	public void onErrot(Session sesion, Throwable error) {
		error.printStackTrace();
	}

	// 服务器主动推送
	public void sendMessage(String message) throws IOException {
		this.session.getBasicRemote().sendText(message);
	}

	// 发送自定义消息
	public static void sendInfo(String message, @PathParam("userId") String userId) throws IOException {
		if (!StringUtils.isEmpty(userId) && webSocketMap.containsKey(userId)) {
			webSocketMap.get(userId).sendMessage(message);
		}
	}

	public static synchronized int getOnlineCount() {
		return onlineCount;
	}

	public static synchronized void addOnlineCount() {
		WebSocketServer.onlineCount++;
	}

	public static synchronized void subOnlineCount() {
		WebSocketServer.onlineCount--;
	}

}
